package com.coocaa.x.service.litecache;

import android.content.Context;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

import com.coocaa.x.framework.app.CoocaaService.AIDLInterface;
import com.coocaa.x.framework.utils.LogUtils;
import com.coocaa.x.service.litecache.LiteCacheHelper.CacheRunnable;
import com.coocaa.x.service.litecache.LiteCacheHelper.LiteCacheHelperCachingListener;
import com.coocaa.x.service.litecache.LiteCacheHelper.LiteCacheHelperLockingListener;
import com.coocaa.x.service.litecache.aidl.ILiteCacheCachingListener;
import com.coocaa.x.service.litecache.aidl.ILiteCacheLockingListener;
import com.coocaa.x.service.litecache.aidl.ILiteCacheService;
import com.coocaa.x.service.litecache.data.common.LiteCacheObject;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by lu on 15-3-13.
 */
public class LiteCacheStub extends ILiteCacheService.Stub implements
        LiteCacheHelperCachingListener, LiteCacheHelperLockingListener {
    private LiteCacheHelper cacheHelper = LiteCacheHelper.getInstance();

    private Map<String, AIDLInterface<ILiteCacheCachingListener>> cachingListeners = new HashMap<String, AIDLInterface<ILiteCacheCachingListener>>();
    private Map<String, AIDLInterface<ILiteCacheLockingListener>> lockingListeners = new HashMap<String, AIDLInterface<ILiteCacheLockingListener>>();
    private Context mContext = null;

    private static void postAction(Runnable r) {
        LiteCacheObject.postAction(r);
    }

    public LiteCacheStub(Context context) {
        mContext = context;
        LiteCacheHelperConfig.CACHE_PATH = context
                .getDir("lite_cache", Context.MODE_WORLD_READABLE).getAbsolutePath();
    }

    @Override
    public void whoAmI() {
        LogUtils.d("wai", "<<LiteCacheService>> who am i??  " + mContext.getPackageName());
    }

    @Override
    public void cache(String url, ILiteCacheCachingListener listener) throws RemoteException {
        CacheRunnable r = cacheHelper.cache(url, this);
        if (listener != null) {
            IBinder binder = listener.asBinder();
            AIDLInterface<ILiteCacheCachingListener> i = new AIDLInterface<ILiteCacheCachingListener>(
                    binder, listener);
            synchronized (cachingListeners) {
                cachingListeners.put(r.getID(), i);
            }
        }
        r.start();
    }

    @Override
    public void lock(String jsonObj, ILiteCacheLockingListener listener) throws RemoteException {
        LogUtils.i("lite", "service lock json:" + jsonObj);
        LiteCacheObject obj = LiteCacheObject.parseJObject(jsonObj, LiteCacheObject.class);
        if (listener != null) {
            synchronized (lockingListeners) {
                AIDLInterface<ILiteCacheLockingListener> l = lockingListeners.get(obj.id);
                if (l == null) {
                    IBinder binder = listener.asBinder();
                    l = new AIDLInterface<ILiteCacheLockingListener>(binder, listener);
                    lockingListeners.put(obj.id, l);
                } else
                    throw new RuntimeException("The cacheobj " + obj
                            + " has already been in locking!!");
            }
        }
        cacheHelper.lock(obj, this);
    }

    @Override
    public void unlock(String jsonObj) throws RemoteException {
        LiteCacheObject obj = LiteCacheObject.parseJObject(jsonObj, LiteCacheObject.class);
        cacheHelper.unlock(obj);
    }

    @Override
    public void onLiteCacheObjectLocked(final LiteCacheObject obj, final boolean success,
                                        final String failmsg, final String content) {
        synchronized (lockingListeners) {
            AIDLInterface<ILiteCacheLockingListener> l = lockingListeners.get(obj.id);
            lockingListeners.remove(obj.id);
            if (l != null) {
                try {
                    l.i.onLiteCacheObjectLocked(obj.toString(), success, failmsg, content);
                    l.i = null;
                    l.binder = null;
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public void onLiteCacheObjectCached(CacheRunnable crun, final LiteCacheObject obj,
                                        final boolean success, final String failmsg, final String extra) {
        synchronized (cachingListeners) {
            final AIDLInterface<ILiteCacheCachingListener> l = cachingListeners.get(crun.getID());
            cachingListeners.remove(crun.getID());
            if (l != null) {
                postAction(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            l.i.onLiteCacheObjectCached(obj.toJSONString(), success, failmsg, extra);
                            l.i = null;
                            l.binder = null;
                        } catch (RemoteException e) {
                            e.printStackTrace();
                        }
                    }
                });
            }
        }
    }
}